package my.mark.mybaibaoxiang.juc.biji06;

import java.util.concurrent.CyclicBarrier;

/**
 * @author wxming.
 * @description :栅栏屏障，让一组线程到达一个屏障（也可以叫同步点）时被阻塞，直到最后一个线程 到达屏障时，屏障才会开门，所有被屏障拦截的线程才会继续运行。
 * CyclicBarrier默认的构造方法是CyclicBarrier（int parties），其参数表示屏障拦截的线 程数量，每个线程调用await方法告CyclicBarrier我已经到达了屏障，然后当前线程被阻塞。
 */
public class CyclicBarrierTest implements Runnable {
    private CyclicBarrier cyclicBarrier;
    private int index;

    public CyclicBarrierTest(CyclicBarrier cyclicBarrier, int index) {
        this.cyclicBarrier = cyclicBarrier;
        this.index = index;
    }

    public void run() {
        try {
            System.out.println("index: " + index);
            index--;
            cyclicBarrier.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(11, new Runnable() {
            public void run() {
                System.out.println("所有特工到达屏障，准备开始执行秘密任务");
                System.out.println("验证“全部到达屏障”和这个哪个先执行");
            }
        });
        for (int i = 0; i < 10; i++) {
            new Thread(new CyclicBarrierTest(cyclicBarrier, i)).start();
        }
        System.out.println("子线程全部启动了");
        cyclicBarrier.await();//11个，当10个子线程包括这行这个11个都到达屏障，才会执行初始化CyclicBarrier时创建的那个“所有特工到达屏障”的线程，TODO 执行完之后才会继续往下执行。给初始化线程打多个断点之后的日志如下：
        /**
         * 子线程全部启动了
         index: 0
         index: 2
         index: 1
         index: 3
         index: 4
         index: 5
         index: 6
         index: 8
         index: 7
         index: 9
         所有特工到达屏障，准备开始执行秘密任务
         验证“全部到达屏障”和这个哪个先执行
         全部到达屏障....
         */
        System.out.println("全部到达屏障....");
    }

}
